﻿// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// Copyright (c) 2011, Dr. Masroor Ehsan
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the author nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 
// $Author: masroore@gmail.com $
// $Id: FirebirdPersistenceProvider.cs 38 2011-10-22 08:19:17Z masroore@gmail.com $
// $Rev: 38 $
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using FirebirdSql.Data.FirebirdClient;
using FluentNHibernate.Cfg.Db;
using MaxTrader.Core;
using MaxTrader.Persistence.Core;

namespace MaxTrader.Persistence.Firebird
{
    public class FirebirdPersistenceProvider : IPersistenceProvider
    {
        private const string DATABASE_FILENAME = @"maxtrader.fdb";

        private const string DATABASE_FOLDER = @"data";

        private const string FIREBIRD_DLL = @"fbembed.dll";

        #region IPersistenceProvider Members

        public string ProviderName
        {
            get { return @"Firebird Persistence Provider"; }
        }

        public decimal ProviderVersion
        {
            get { return 0.1m; }
        }

        public string StorageLocation { get; set; }

        public IPersistenceConfigurer Configuration
        {
            get { return new FirebirdConfiguration().ConnectionString(GetConnectionString()); }
        }

        public IPersistenceMapping Mapping
        {
            get { return FirebirdPersistenceMapping.Instance; }
        }

        public string GetConnectionString()
        {
            var csb = new FbConnectionStringBuilder
                          {
                              Database = LocateDatabaseFile(),
                              ClientLibrary = LocateFirebirdDll(),
                              UserID = @"SYSDBA",
                              ServerType = FbServerType.Embedded,
                              Dialect = 3
                          };

            return csb.ToString();
        }

        #endregion

        private static string LocateDllAbsolutePath(string rootFolder, string dllName)
        {
            var dllPath = Path.Combine(rootFolder, dllName);
            if (!File.Exists(dllPath))
            {
                dllPath = Path.Combine(
                    Path.Combine(
                        rootFolder,
                        Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
                        ),
                    dllName);
            }

            return File.Exists(dllPath) ? dllPath : string.Empty;
        }

        private static string LocateFirebirdDll()
        {
            string localPath = PathUtilities.GetAssemblyFolder();
            if (!string.IsNullOrEmpty(localPath))
            {
                string dllPath = LocateDllAbsolutePath(Path.GetDirectoryName(localPath), FIREBIRD_DLL);
                if (string.IsNullOrEmpty(dllPath))
                {
                    var entryAssembly = Assembly.GetEntryAssembly();

                    if (entryAssembly != null)
                    {
                        dllPath = LocateDllAbsolutePath(Path.GetDirectoryName(entryAssembly.Location), FIREBIRD_DLL);
                    }
                }

                return string.IsNullOrEmpty(dllPath) ? FIREBIRD_DLL : dllPath;
            }

            return FIREBIRD_DLL;
        }

        private string LocateDatabaseFile()
        {
            string dbFilename;

            if (!string.IsNullOrEmpty(StorageLocation))
            {
                dbFilename = Path.Combine(Path.GetDirectoryName(StorageLocation), DATABASE_FILENAME);
                if (File.Exists(dbFilename))
                {
                    return dbFilename;
                }
            }

            dbFilename = Path.Combine(
                Path.Combine(
                    Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath),
                    DATABASE_FOLDER),
                DATABASE_FILENAME);
            //dbFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DATABASE_FILENAME);
            return dbFilename;
        }
    }
}